﻿using Aop.Api.Domain;
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Lg.Core.Extensions;
using Lg.Core.Exceptions;

namespace Lg.Core.RidAuthor
{
    public class Rider
    {
        readonly RiderBuilder _builder;
        public string Rid { get; set; }
        public RiderIdentityTypeOptions IdentityType { get; set; }
        public IRidUser? User {  get; set; }
        public RsaKeyModel? RsaKey { get; set; }
        public string? AesKey { get; set; }
        public List<RiderCacheModel>? Caches { get; set; }
        /// <summary>
        /// 构造一个rider，默认为匿名用户
        /// 构造时自动分配一个rid
        /// 构造时自动生RSA对像，含一对密钥
        /// </summary>
        /// <param name="builder">一个含当前注入cache、httpcontext、IdWorker（雪花id）实例的对像，该builder应以注入模式使用，以确保拿到的属性对像均为注入的相同实例</param>
        /// <param name="IdentityType">Rider的用户类型，默认为匿名用户</param>
        public Rider(RiderBuilder builder,RiderIdentityTypeOptions IdentityType=RiderIdentityTypeOptions.Anonymous)
        {
            this._builder = builder;
            var context = builder.HttpContext;
            var snowid = builder.IdWorker.NextId();
            string key = Lg.Core.Encryption.MD5.Encrypt(context.Request.Headers.UserAgent + context.Connection.RemoteIpAddress?.ToString() + snowid);
            this.Rid = $"{Math.Abs(key.GetHashCode())}-{snowid}";
            using var rsaHelper = new Lg.Core.Encryption.RSAHelper();
            RsaKey=new RsaKeyModel { PrivateKey=rsaHelper.privateKey,PublicKey=rsaHelper.publicKey };
        }

        /// <summary>
        /// 较验rid是否合法
        /// </summary>
        /// <returns></returns>
        public bool CheckRid()
        {
            var context = this._builder.HttpContext;
            var snowid = this.Rid.Split('-')[1];
            string key = Lg.Core.Encryption.MD5.Encrypt(context.Request.Headers.UserAgent + context.Connection.RemoteIpAddress?.ToString() + snowid);
            key = $"{Math.Abs(key.GetHashCode())}-{snowid}";
            return this.Rid == key;
        }

        /// <summary>
        /// 解析客户端的AES key并赋值给当前的Rider对像，支持自定义错误事件
        /// </summary>
        /// <param name="key"></param>
        /// <param name="onError"></param>
        public void InitAES(string key,Action<string>? onError=null)
        {
            onError ??= (msg) => { throw new LgException(msg); };
            try
            {
                if (RsaKey != null)
                {
                    using var rsaHelper = new Lg.Core.Encryption.RSAHelper(RsaKey.PublicKey, RsaKey.PrivateKey);
                    this.AesKey = rsaHelper.Dencrypt(key);
                }
                else
                {
                    onError("缺少RSA密钥！");
                }
            }
            catch (Exception e)
            {
                onError(e.Message);
            }
            
        }

        /// <summary>
        /// 解密客户端AES加密的数据
        /// 用客户端传递的rid来获取存储的AES密钥
        /// </summary>
        /// <param name="rid">客户端请求ID，系统签发</param>
        /// <param name="ciphertext">密文</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public string AesDecode(string ciphertext)
        {
            var aesKey = this.AesKey ?? throw new LgException("缺少AES密钥！");
            return ciphertext.AesDecrypt(aesKey);
            
        }

        /// <summary>
        /// 进行AES加密
        /// </summary>
        /// <param name="rid">客户端请求ID，系统签发</param>
        /// <param name="plaintext">明文</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public string AESEncode( string plaintext)
        {
            var aesKey = this.AesKey ?? throw new LgException("缺少AES密钥！");
           return plaintext.AesEncrypt(aesKey);
        }
    }
}
